Syntax10.Scn.Fnt FoldElems Syntax10.Scn.Fnt (*------------------------------------------------------------ Compare files. Search for a literal string in a sequence of files. Search for clients and imports of a specific module. Search for attributes in info elements Find.Diff ^ Compares two texts starting from the two most recent selections. Sets new selections at the first position where the two texts differ. Find.Domain {filename} ~ Specify the files in which Find.All should search for a pattern. Find.All ^ Searches the selection in the files specified with Find.Domain. Lists all lines containing the pattern. Find.AllInfo ^ The selection must be of the form item = pattern where item is one of the headings in an info element (Title, Author, ...) and pattern is any character sequence up to the end of the selection. Lists all modules specified with Find.Domain containing the pattern in their info elements. Find.Clients (name | ^) List all client modules which import module . Clients are only searched for in the current directory. Find.Imports (name | ^) List all modules imported by module . The modules are listed together with their keys. ------------------------------------------------------------*) Syntax10i.Scn.Fnt InfoElems Alloc Syntax10.Scn.Fnt StampElems Alloc 4 May 95 "Title": Find "Author": HM (mainly), CS (added AllInfo) "Abstract": Provides you with the possibility to search strings in several files, to see which files are imported by several files, to see by which files several files are imported and to search several files after additional information (title, author, version, keywords etc.). "Keywords": search, import, client, additional info "Version": 1.0 "From": 28.10.94 16:40:44 "Until": "Changes": "Hints": This text can again contain arbitrary text elements! MarkElems Alloc Syntax10.Scn.Fnt VAR a, b: CHAR; BEGIN Files.Read(r, a); Files.Read(r, b); n := SHORT(ASH(ORD(a), 8) + ORD(b)) END ReadInt; Syntax10.Scn.Fnt VAR a, b, c, d: CHAR; BEGIN Files.Read(r, a); Files.Read(r, b); Files.Read(r, c); Files.Read(r, d); n := ASH(ORD(a), 24) + ASH(ORD(b), 16) + ASH(ORD(c), 8) + ORD(d) END ReadLInt; Syntax10.Scn.Fnt VAR t: Texts.Text; beg, end, time: LONGINT; BEGIN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "^") THEN Oberon.GetSelection(t, beg, end, time); IF time >= 0 THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s) END END ScanPar; Syntax10.Scn.Fnt VAR v: MenuViewers.Viewer; x, y: INTEGER; t1: Texts.Text; menu: TextFrames.Frame; buf: Texts.Buffer; BEGIN IF Files.Old("Edit.Menu.Text") = NIL THEN menu := TextFrames.NewMenu(name, stdMenu) ELSE menu := TextFrames.NewMenu(name, ""); NEW(t1); Texts.Open(t1, "Edit.Menu.Text"); NEW(buf); Texts.OpenBuf(buf); Texts.Save(t1, 0, t1.len, buf); Texts.Append(menu.text, buf) END; Oberon.AllocateUserViewer(0, x, y); v := MenuViewers.New(menu, TextFrames.NewText(t, 0), TextFrames.menuH, x, y) END OpenViewer; Syntax10.Scn.Fnt CONST bufSize = 31744; (*2**15 - 1024*) textTag = 496; oldTextTag = -4095; f: Files.File; r: Files.Rider; n, pos: LONGINT; i, j, i0: INTEGER; ch, patj: CHAR; found: BOOLEAN; tab: ARRAY 265 OF SHORTINT; text: ARRAY bufSize OF CHAR; BEGIN (*----- open file *) f := Files.Old(fn); IF f = NIL THEN RETURN END; Files.Set(r, f, 0); Files.ReadInt(r, i); IF (i = textTag) OR (i = oldTextTag) THEN pos := 0; (*Files.ReadLInt(r, pos); -- modified to search also in collapsed Fold segments*) (*----- initialize tab *) Texts.WriteString(w, "--- "); Texts.WriteString(w, fn); Texts.WriteLn(w); FOR i := 0 TO 255 DO tab[i] := SHORT(m) END; FOR i := 0 TO m-2 DO tab[ORD(pat[i])] := SHORT(m - i - 1) END; patj := pat[m-1]; found := FALSE; LOOP (*----- read text[0..n-1] *) n := Files.Length(f) - pos; IF n > bufSize THEN n := bufSize END; IF n < m THEN EXIT END; Files.Set(r, f, pos); Files.ReadBytes(r, text, n); (*----- search pat in text[0..n-1] *) i := m - 1; j := i; WHILE i < n DO IF text[i] = patj THEN i0 := i; REPEAT DEC(i); DEC(j) UNTIL (j < 0) OR (text[i] # pat[j]); IF j < 0 THEN (*------ found: print result *) found := TRUE; WHILE (i >= 0) & (text[i] # CR) & (text[i] >= TAB) DO DEC(i) END; INC(i); Files.Set(r, f, pos + i); REPEAT Files.Read(r, ch); Texts.Write(w, ch); INC(i) UNTIL (ch = CR) OR (ch < TAB) OR (r.eof) ELSE i := i + tab[ORD(text[i])] END; IF i <= i0 THEN i := i0 + 1 END; j := m - 1 ELSE i := i + tab[ORD(text[i])] END END; pos := pos + i - m + 1 END; IF found THEN Texts.WriteLn(w); Texts.Append(out, w.buf) ELSE Texts.OpenWriter(w) END ELSE Texts.WriteString(w, fn); Texts.WriteString(w, " is no text file"); Texts.WriteLn(w); Texts.Append(Oberon.Log, w.buf) END Search; Syntax10.Scn.Fnt VAR f: Files.File; r: Files.Rider; ch: CHAR; s: ARRAY 32 OF CHAR; i, j, dummy, entries, cmds, ptrs, imps: INTEGER; key: LONGINT; BEGIN f := Files.Old(name); IF f # NIL THEN i := 0; WHILE name[i] # 0X DO INC(i) END; name[i-3] := "M"; name[i-2] := "o"; name[i-1] := "d"; Files.Set(r, f, 6); ReadInt(r, entries); ReadInt(r, cmds); ReadInt(r, ptrs); ReadInt(r, dummy); ReadInt(r, imps); Files.Set(r, f, 34); REPEAT Files.Read(r, ch) UNTIL ch = 0X; (*skip name*) Files.Set(r, f, Files.Pos(r) + 1 + 2*entries + 1); (*skip entries*) FOR i := 1 TO cmds DO (*skip commands*) REPEAT Files.Read(r, ch) UNTIL ch = 0X; ReadInt(r, dummy) END; Files.Set(r, f, Files.Pos(r) + 1 + 4*ptrs + 1); (*skip pointer offsets*) FOR i := 1 TO imps DO ReadLInt(r, key); j := 0; REPEAT Files.Read(r, ch); s[j] := ch; INC(j) UNTIL ch = 0X; IF s = fileName THEN Out.String(" "); Out.String(name); Out.Ln END END END CheckObjFile; Syntax10.Scn.Fnt Syntax8i.Scn.Fnt BEGIN WHILE (npos >= 0) & (mpos >= 0) & (mask[mpos] # "*") DO IF name[npos] # mask[mpos] THEN RETURN FALSE END; DEC(npos); DEC(mpos) END; (* ----- name empty | mask empty | mask ends with "*" *) IF mpos < 0 THEN RETURN npos < 0 END; (* ----- name empty | mask ends with "*" *) WHILE (mpos >= 0) & (mask[mpos] = "*") DO DEC(mpos) END; IF mpos < 0 THEN RETURN TRUE END; (* ----- name empty | mask still to be matched *) WHILE npos >= 0 DO IF Match(name, mask, npos, mpos) THEN RETURN TRUE END; DEC(npos) END; RETURN FALSE END Match; Syntax10b.Scn.Fnt Syntax10.Scn.Fnt VAR s: Texts.Scanner; f, last: File; BEGIN file := NIL; last := NIL; ScanPar(s); WHILE (s.class = Texts.Name) OR (s.class = Texts.String) DO NEW(f); f.next := NIL; IF last = NIL THEN file := f ELSE last.next := f END; last := f; COPY(s.s, f.name); Texts.Scan(s); WHILE (s.class = Texts.Char) & (s.c = "/") DO Texts.Scan(s); Texts.Scan(s) END END Domain; Syntax10.Scn.Fnt FoldElems Syntax10.Scn.Fnt VAR t: Texts.Text; r: Texts.Reader; beg, end, time: LONGINT; ch: CHAR; BEGIN Oberon.GetSelection(t, beg, end, time); IF time > 0 THEN Texts.OpenReader(r, t, beg); m := 0; WHILE beg < end DO Texts.Read(r, ch); IF m < 127 THEN pat[m] := ch END; INC(m); INC(beg) END; pat[m] := 0X END; END ReadPattern; VAR pat: ARRAY 128 OF CHAR; m: INTEGER; f: File; PROCEDURE ReadPattern (VAR pat: ARRAY OF CHAR; VAR m: INTEGER); BEGIN ReadPattern(pat, m); out := TextFrames.Text(""); OpenViewer(pat, out); f := file; WHILE f # NIL DO Search(f.name, pat, m); f := f.next END All; Syntax10.Scn.Fnt FoldElems Syntax10.Scn.Fnt VAR time: LONGINT; v: Viewers.Viewer; x: INTEGER; f: Display.Frame; BEGIN time := -1; x := 0; F := NIL; WHILE x < Display.Width DO v := Viewers.This(x, 0); WHILE v.state > 1 DO f := v.dsc.next; WITH f: TextFrames.Frame DO IF f.hasSel & (f.time > time) THEN F := f; pos := f.selbeg.pos; time := f.time END ELSE END; v := Viewers.Next(v) END; x := x + v.W END; IF F # NIL THEN TextFrames.RemoveSelection(F); TextFrames.RemoveCaret(F) END END GetSelection; Syntax10.Scn.Fnt VAR x: LONGINT; BEGIN IF pos > TextFrames.Pos(f, f.X + f.W - 1, f.Y) THEN x := pos - 150; IF x < 0 THEN x := 0 END; TextFrames.Show(f, x) END; TextFrames.SetSelection(f, pos, pos+1) END ShowSelection; VAR f1, f2: TextFrames.Frame; p1, p2: LONGINT; r1, r2: Texts.Reader; ch1, ch2: CHAR; PROCEDURE GetSelection(VAR F: TextFrames.Frame; VAR pos: LONGINT); PROCEDURE ShowSelection(f: TextFrames.Frame; pos: LONGINT); BEGIN GetSelection(f1, p1); GetSelection(f2, p2); IF (f1 # NIL) & (f2 # NIL) THEN Texts.OpenReader(r1, f1.text, p1); Texts.OpenReader(r2, f2.text, p2); REPEAT Texts.Read(r1, ch1); INC(p1); Texts.Read(r2, ch2); INC(p2); UNTIL (ch1 # ch2) OR (ch1 = 0X); IF (ch1 = 0X) OR (ch2 = 0X) THEN DEC(p1); DEC(p2) END; ShowSelection(f1, p1-1); ShowSelection(f2, p2-1) END Diff; Syntax10.Scn.Fnt FoldElems Syntax10.Scn.Fnt Texts.OpenScanner(menuS, menuT, 0); Texts.Scan(menuS); WHILE ~menuS.eot DO IF (menuS.class = Texts.String) & (menuS.s = item) THEN (* if it is the right item *) Texts.OpenReader(copyR, t, Texts.Pos(menuS) - 2); Texts.Read(copyR, copyCh); i := 0; r2 := r; WHILE (~copyR.eot) & (copyCh # '"') DO INC(i); Texts.Read(copyR, copyCh) END; NEW(text, i + 1); r := r2; i := 0; WHILE (~copyR.eot) & (copyCh # '"') DO INC(i); text[i] := copyCh; Out.Char(copyCh); Texts.Read(copyR, copyCh) END; text[i] := 0X; IF Match(text^, pat, i - 1, m - 1) THEN FOR i := 0 TO i DO Texts.Write(w, ch) END END; Texts.OpenScanner(menuS, t, Texts.Pos(copyR) - 1); END; Texts.Scan(menuS); END END; (* character was no InfoElem *) Texts.Read(r, ch) END; t, infoT: Texts.Text; r, infoR: Texts.Reader; ch, commentCh: CHAR; menuItem: ARRAY 16 OF CHAR; text: ARRAY 10000 OF CHAR; i, textLen, patLen: LONGINT; BEGIN Texts.WriteString(w, "--- "); Texts.WriteString(w, fn); Texts.WriteString(w, ", matches for "); Texts.WriteString(w, item); Texts.WriteString(w, " = "); Texts.WriteString(w, pat); Texts.WriteLn(w); NEW(t); Texts.Open(t, fn); Texts.OpenReader(r, t, 0); Texts.ReadElem(r); WHILE ~r.eot DO IF r.elem IS InfoElems.Elem THEN (* InfoElem found *) infoT := r.elem(InfoElems.Elem).menu; (* get text of InfoElem *) Texts.OpenReader(infoR, infoT, 0); Texts.Read(infoR, ch); WHILE ~infoR.eot DO WHILE (~infoR.eot) & (ch # '"') & (ch # "'") DO Texts.Read(infoR, ch) END; IF ~infoR.eot THEN commentCh := ch END; Texts.Read(infoR, ch); i := 0; WHILE (~infoR.eot) & (ch # commentCh) DO menuItem[i] := ch; Texts.Read(infoR, ch); INC(i) END; menuItem[i] := 0X; WHILE (~infoR.eot) & ((ch = "'") OR (ch = '"') OR (ch = " ") OR (ch = TAB) OR (ch = ":")) DO Texts.Read(infoR, ch) END; i := 0; WHILE (~infoR.eot) & (ch # '"') & (ch # "'") & (i < LEN(text) - 1) DO IF (ch # TAB) & (ch # CR) THEN text[i] := ch; INC(i) END; Texts.Read(infoR, ch) END; text[i] := 0X; IF menuItem = item THEN patLen := 0; WHILE pat[patLen] # 0X DO INC(patLen) END; textLen := 0; WHILE text[textLen] # 0X DO INC(textLen) END; IF Match(text, pat, textLen, patLen) THEN i := 0; WHILE text[i] # 0X DO Texts.Write(w, text[i]); INC(i) END END END END END; Texts.ReadElem(r) END; Texts.WriteLn(w); Texts.Append(out, w.buf); END InfoSearch; Syntax10.Scn.Fnt Syntax10i.Scn.Fnt FoldElems Syntax10.Scn.Fnt VAR t: Texts.Text; r: Texts.Reader; s: Texts.Scanner; beg, end, time: LONGINT; ch: CHAR; BEGIN Oberon.GetSelection(t, beg, end, time); IF time > 0 THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s); IF s.class IN {Texts.Name, Texts.String} THEN COPY(s.s, item); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "=") THEN Texts.Scan(s); Texts.OpenReader(r, t, Texts.Pos(s) - 2); m := 0; beg := Texts.Pos(s) - 2; WHILE beg < end DO Texts.Read(r, ch); IF m < (LEN(pat) - 1) THEN pat[m] := ch END; INC(m); INC(beg) END; pat[m] := 0X END; END; END; END ReadPattern; VAR pat: ARRAY 128 OF CHAR; item: ARRAY 16 OF CHAR; m: INTEGER; f: File; PROCEDURE ReadPattern; BEGIN ReadPattern; out := TextFrames.Text(""); OpenViewer(pat, out); f := file; WHILE f # NIL DO InfoSearch(f.name, pat, item); f := f.next END AllInfo; Syntax10.Scn.Fnt VAR i: INTEGER; BEGIN In.Open; In.Name(fileName); IF In.Done THEN i := 0; WHILE fileName[i] # 0X DO INC(i) END; IF (i >= 4) & (fileName[i-4] = ".") THEN fileName[i-4] := 0X END; Out.String("modules importing "); Out.String(fileName); Out.Char(":"); Out.Ln; Directories.EnumerateFiles(0, 0, "*.Obj", CheckObjFile) END; END Clients; Syntax10.Scn.Fnt CONST TAB = 9X; VAR f: Files.File; r: Files.Rider; ch: CHAR; a: ARRAY 256 OF CHAR; i, j, dummy, entries, cmds, ptrs, imps: INTEGER; key: LONGINT; BEGIN In.Open; In.Name(a); IF In.Done THEN i := 0; WHILE a[i] # 0X DO INC(i) END; IF (i >= 4) & (a[i-4] = ".") THEN i := i - 4 ELSE a[i] := "." END; a[i+1] := "O"; a[i+2] := "b"; a[i+3] := "j"; a[i+4] := 0X; f := Files.Old(a); IF f # NIL THEN Files.Set(r, f, 6); ReadInt(r, entries); ReadInt(r, cmds); ReadInt(r, ptrs); ReadInt(r, dummy); ReadInt(r, imps); Files.Set(r, f, 34); REPEAT Files.Read(r, ch) UNTIL ch = 0X; (*skip name*) Files.Set(r, f, Files.Pos(r) + 1 + 2*entries + 1); (*skip entries*) FOR i := 1 TO cmds DO (*skip commands*) REPEAT Files.Read(r, ch) UNTIL ch = 0X; ReadInt(r, dummy) END; Files.Set(r, f, Files.Pos(r) + 1 + 4*ptrs + 1); (*skip pointer offsets*) Out.String(a); Out.Char(TAB); Out.Char("["); Out.Int(key, 0); Out.String("] imports:"); Out.Ln; FOR i := 1 TO imps DO ReadLInt(r, key); j := 0; REPEAT Files.Read(r, ch); a[j] := ch; INC(j) UNTIL ch = 0X; Out.Char(TAB); Out.String(a); Out.Char(TAB); Out.Char("["); Out.Int(key, 0); Out.Char("]"); Out.Ln END END END Imports; Documentation MODULE Find; IMPORT Display, Files, Directories, Oberon, Viewers, MenuViewers, TextFrames, Texts, In, Out, InfoElems; CONST stdMenu = "System.Close System.Copy System.Grow Edit.Search Edit.Store "; CR = 0DX; TAB = 09X; File = POINTER TO FileDesc; FileDesc = RECORD name: ARRAY 256 OF CHAR; next: File END; file: File; fileName: ARRAY 256 OF CHAR; w: Texts.Writer; out: Texts.Text; PROCEDURE ReadInt (VAR r: Files.Rider; VAR n: INTEGER); PROCEDURE ReadLInt (VAR r: Files.Rider; VAR n: LONGINT); PROCEDURE ScanPar (VAR s: Texts.Scanner); PROCEDURE OpenViewer(name: ARRAY OF CHAR; t: Texts.Text); PROCEDURE Search (fn: ARRAY OF CHAR; pat: ARRAY OF CHAR; m: INTEGER); PROCEDURE CheckObjFile (VAR name: ARRAY OF CHAR; time, date, len: LONGINT; isDir: BOOLEAN; VAR continue: BOOLEAN); PROCEDURE Match (VAR name, mask: ARRAY OF CHAR; npos, mpos: LONGINT): BOOLEAN; (* -- commands -- *) PROCEDURE Domain*; (* {filename} ~ *) PROCEDURE All*; (* ^ *) PROCEDURE Diff*; (* compares two texts from the last two selections; sets selection to first difference *) (* -- PowerMac-specific commands -- *) PROCEDURE InfoSearch (fn: ARRAY OF CHAR; pat: ARRAY OF CHAR; item: ARRAY OF CHAR); PROCEDURE AllInfo*; (** ^ format: item = searchPattern where item IN {"Title", "Author", "Abstract", "Keywords", "Version", "From", "Until", "Hints", "Changes"}, searchPattern must match exactly or contain asterisks *) PROCEDURE Clients*; PROCEDURE Imports*; BEGIN file := NIL; Texts.OpenWriter(w) END Find.